;sj1-1.asm
assume cs:code

data segment
    db 10 dup (0)
data ends

code segment
    start:
        ; 选择数字 5a9768h=>5937000
        mov ax,data
        mov ds,ax ;数据段

         mov ax,9768h
        mov dx,005ah
        mov si,0   ;记忆在数据栈中有多少个数据
        call dtoc
       
        mov ax, 4c00H
        int 21H
    ;---------------
    ;将dword数字转为字符串
    ;
    ;参数: ax dword低位
    ;参数: dx dword高位
    ;返回：无
    ;---------------
    dtoc:
        push ax
        push dx
        push cx
        push bx ;divdw中使用到了bx
        push bp ;divdw中使用到了bp
        push si ;数据入栈保护
        
    rem:
        mov cx,10    ;除数为零
        mov bx,0     ;在divdw中使用过，恢复为零
        call divdw   ;返回：ax 结果的低16位 dx 结果的低16位 bp 余数 

        push ax      ;我在这个地方调试了好久
        push dx      ;保护数据，一会需要做加法判断是否为零

        add ax,dx    
        mov cx,ax    ;判断商为是否为零

        pop dx
        pop ax       ;跳出之前要恢复原来的数值

        jcxz last    ;跳出，数字循环完毕
        add bp,30H   ;获取十进制数码对应的ASII码
        push bp      ;存储余数
        
        inc si       ;在栈中有多少个数据 解决题5
        jmp short rem ;继续读取字符串

    ;处理边界值 最后一次商为零，也需要压栈
    last: 
        add bp,30H    ;字符零，ASCII是30h
        push bp       ;边界值为零
        inc si  

        mov cx,si        ;loop 循环读取存储的字符数据  关键点
        mov si,0         ;数据偏移地址
    write:
        pop ds:[si] ;将asii写入数据段
        inc si
        loop write
    exit:
        pop si 
        pop bp 
        pop bx 
        pop cx
        pop dx
        pop ax
        ret
    ;-------------
    ;被除数是32位的除法
    ;
    ;参数：ax dword低16位
    ;参数：dx dword高16位
    ;参数：cx 除数
    ;返回：ax 结果的低16位 
    ;返回：dx 结果的低16位
    ;返回：bp 余数 不在使用cx避免混乱
    ;-------------
    divdw:                      ;子程序开始
        push ax             ;将被除数低16位先压栈保存。
        mov ax, dx          ;（ax）=（dx）
        mov dx, 0000H       ;
        div cx              ;此时（dx）=0000H，（ax）=000FH，组合成0000000FH。
        mov bx, ax          ;将H/N结果的商先保存在bx中，（bx）=0001H
        
        pop ax              ;将L值弹栈到ax
        div cx              ;此时（dx）=0005H，（ax）=4240H,组合成54240H
        mov bp, dx          ;返回值（cx）等于最终结果的余数
        mov dx, bx          ;最终结果高16位值=（bx）

        ret

code ends
end start